// Fill out your copyright notice in the Description page of Project Settings.


#include "SdfGenUtils.h"
#include "FSDFUtils.h"
#include "FTTFUtils.h"
#include "TextInfos.h"
#include "Engine/Texture2DDynamic.h"

void FSdfGenUtils::GenerateSDF(const FString& SingleChar, const FString& FontPath, FTextFontInfo& FontInfo,
                               int32 FontSize, float Scale)
{
	FImage GrayScaleImage;
	SDFGen::FTTFUtils::FontMetrics Metrics;
	SDFGen::FTTFUtils::RenderToFontBitmap(&GrayScaleImage, &Metrics, SingleChar, FontPath, FontSize);

	SDFGen::FSDFUtils Sdf;
	FImage SdfImage;
	Sdf.Generate(&GrayScaleImage, &SdfImage);

	const int32 SrcWidth = SdfImage.GetWidth();
	const int32 SrcHeight = SdfImage.GetHeight();
	const int32 DesiredWidth = static_cast<int32>(SrcWidth * Scale);
	const int32 DesiredHeight = static_cast<int32>(SrcHeight * Scale);

	FImage DestImage;
	SdfImage.ResizeTo(DestImage, DesiredWidth, DesiredHeight, ERawImageFormat::BGRA8, EGammaSpace::sRGB);

	FontInfo.Bitmap = CreateTexture2DDynamic(DesiredWidth, DesiredHeight, DestImage.AsBGRA8());
	FontInfo.Width = static_cast<int16>(DesiredWidth / Metrics.AdvanceH);
	FontInfo.Height = static_cast<int16>(DesiredHeight / Metrics.AdvanceV);
	FontInfo.AdvanceH = Metrics.AdvanceH;
	FontInfo.AdvanceV = Metrics.AdvanceV;
	FontInfo.BearingH = Metrics.BearingH;
	FontInfo.BearingV = Metrics.BearingV;
	FontInfo.BitmapTop = Metrics.BitmapTop;
	FontInfo.BitmapLeft = Metrics.BitmapLeft;
}

UTexture2DDynamic* FSdfGenUtils::CreateTexture2DDynamic(const int32 Width, const int32 Height,
                                                        const TArrayView64<FColor>& Data)
{
	UTexture2DDynamic* Texture2DDynamic = UTexture2DDynamic::Create(Width, Height);
	if (Texture2DDynamic)
	{
		Texture2DDynamic->UpdateResource();
		FTexture2DDynamicResource* TextureResource = static_cast<FTexture2DDynamicResource*>(Texture2DDynamic->GetResource());

		TArray<uint8> RawData = ConvertColorArrayToUint8Array(Data);

		ENQUEUE_RENDER_COMMAND(FWriteRawDataToDyn)
		(
			[TextureResource, RawData](FRHICommandListImmediate& FRHICommandList)-> void
			{
				TextureResource->WriteRawToTexture_RenderThread(RawData);
			}
		);
	}
	return Texture2DDynamic;
}

TArray<uint8> FSdfGenUtils::ConvertColorArrayToUint8Array(const TArrayView64<FColor>& SrcData)
{
	TArray<uint8> DstData;
	DstData.SetNumZeroed(SrcData.Num() * 4);
	for (int32 i = 0; i < SrcData.Num(); i++)
	{
		DstData[i * 4] = SrcData[i].B;
		DstData[i * 4 + 1] = SrcData[i].G;
		DstData[i * 4 + 2] = SrcData[i].R;
		DstData[i * 4 + 3] = SrcData[i].A;
	}
	return DstData;
}
